               [ Target: Crackme #1 by MrStop ]

 pH#3 .............F.u.l.l..R.e.v.e.r.s.e............. [    #Sadrzaj    ]
 0x01 ................................................ [ Intro          ]
 0x02 ................................................ [ Tools of trade ]
 0x03 ................................................ [ Fishing 1      ]
 0x04 ................................................ [ Fishing 2      ]
 0x05 ................................................ [ Fishing 3      ]
 0x06 ................................................ [ Outro & Greetz ]


--[ 0x01 ]----------------------------------------------[     Intro     ]

  Sada  cemo  "upecati"  par  seriskih  brojeva  uz  pomoc  naseg [h]Olly
debuggera ;)

--[ 0x02 ]---------------------------------------------[ Tools of trade ]

  Da bi smo "popravili" ovaj crackme, trebace nam neki "vaspitni" alati:

 [+] OllyDBG v.1.10 ............................... http://www.ollydbg.de
 [+] HexDecChar v.0.4 ........................ http://ap0x.headcoders.net

  i naravno meta:

 [+] Crackme #1    ....................................... my.target3.zip

  Svi  ovi alati su neophodni svakom reverseru pa predlazem da ako ih vec
nemate,  podhitno  ih  nabavite! Bez njih se dalje citanje ovog teksta ne
isplati!                                                                 

--[ 0x03 ]---------------------------------------------[   Fishing  #1  ]

    Vec  smo  naucili  razne  nacine za hvatanje seriskih brojeva koji se
nalaze  u  formi stringa u memoriji fajla, ali sta ako se seriski brojevi
ne nalaze u ovom obliku. Ovaj slucaj cemo razmotriti na meti Crackme1.exe
koju  cemo  otvoriti  pomocu  Ollya.  Kao  sto vidite ova meta ima ukupno
cetiri nivoa, a mi cemo ovde resiti samo tri. Cetvrti nivo ostavljam vama
za vezbu. 

Text strings referenced in Crackme1:.text, item 4
 Address=004012E0
 Disassembly=PUSH Crackme1.00403000
 Text string=ASCII "Level 1 Complated"

  Posle otvoranja mete pomocu Ollya potrazicemo karakteristicne stringove
koji se odnose na level1. I u string referencama cemo videti sledece:

004012E0 68 00304000  	PUSH 00403000   |Text = "Level 1 Complated"

  Posto se negde iznad proverava tacnost seriskog broja odskrolovacemo na
pocetak  ovog  CALLa i postavicemo break-point na njegov pocetak, odnosno
postavicemo  break-point  na  004012A0.  Posto  smo ovo uradili mozemo da
unesemo  u  metu  seriski  broj  po zelji. Ja sam uneo 111111 i pritisnuo
Register  sto me je odvelo do mog break-pointa. Dalje slobodno traceujemo
kroz kod sa F8 sve do adrese 004012B4 gde se ocigledno proverava da li je
unet bilo koji seriski broj. Posto je EAX jednak 6, odnosno duzini unetog
seriskog  broja,  a  ESP  pokazuje na uneti seriski broj, znamo da smo na
pravom mestu. Dalje se krecemo kroz kod sve dok ne dodjemo do:

004012BB 8136 504F5453 XOR DWORD PTR DS:[ESI],53544F50
004012C1 8176 04 454C5>XOR DWORD PTR DS:[ESI+4],52554C45

 Ocigledno je da je ovo kod za proveru tacnosti seriskog broja iz razloga
sto  se odmah ispod ovoga nalaze skokovi koji odlucuju o tome da li ce se
prikazati  poruka  o  tacnosti unetog seriskog broja. Dakle sada treba da
saznamo  kako  se  to proverava uneti seriski broj. Da bi smo ovo uradili
pogledacemo  sta  se  to  nalazi  na  ESI adresi kada smo sa izvrsavanjem
programa  dosli  do  adrese  004012BB.  Ako uradimo Follow in dump na ESI
registar videcemo ovo:

0012FB00  31 31 31 31 31 31 00 00  111111..

  Dakle  prve  cetiri cifre naseg seriskog broja se XORuju sa 53544F50. A
onda  se  na  adresi  004012C1 i druge cetiri cifre naseg unetog seriskog
broja  XORuju  sa  52554C45.  Kada  se  izvrsi  i ova druga komanda sledi
provera tacnosti unetog seriskog broja pomocu dve sledece komande:

004012C8  813E 123D3525 CMP DWORD PTR DS:[ESI],25353D12
004012CE  75 21         JNZ SHORT Crackme1.004012F1
004012D0  817E 04 2A6D7 CMP DWORD PTR DS:[ESI+4],73746D2A
004012D7  75 18         JNZ SHORT Crackme1.004012F1
       
  Kao sto vidimo XORovane vrednosti prvog i drugog dela seriskog broja se
porede  sa  25353D12  i 73746D2A. Ovo nije nikakav problem. Malo reversne
matematike  i  resecemo  nas  problem,  to jest pronacicemo tacan seriski
broj. Dakle:

Deo_seriskog_broja_1 XOR 53544F50 = 25353D12
Deo_seriskog_broja_2 XOR 52554C45 = 73746D2A

 Posto je XORovanje revezibilna funkcija onda imamo:

Deo_seriskog_broja_1 = 53544F50 XOR 25353D12
Deo_seriskog_broja_2 = 52554C45 XOR 73746D2A

 A ovo mozemo da izracunamo:

Deo_seriskog_broja_1 = 76617242
Deo_seriskog_broja_2 = 2121216F

  Ostaje  nam  jos  samo da pretvorimo ove hexadecimalne brojeve u string
koji  se  unosi. Srecom po nas HexDecChar ovo moze da uradi mnogo brze od
nas  i  stoga  u  njemo  izabiramo mod 2 umesto moda 1 jer pretvaramo ceo
sadrzaj registra u string. Kada paste-ujemo Deo_seriskog_broja_1 kao Char
ce se pokazati string varB. Ali posto su registri uvek invertovani moramo
da uradimo i invert register, ondnosno klikom na zelenu strelicu dobijamo
umesto    varB,    string  Brav.  A  kada  isti  postupak  uradimo  i  za
Deo_seriskog_broja_2    dobijamo   string  o!!!.  Dakle  ceo  seriski  je
Deo_seriskog_broja_1  +  Deo_seriskog_broja_2  =  Bravo!!!.  Konacno  kad
unesemo  tacan  seriski broj u metu dobijamo odgovor Level 1 ComplAted!!!
Predjimo sada na Level 2.

--[ 0x04 ]---------------------------------------------[   Fishing  #2  ]

  Posto  smo sa izuzetnom lakocom resili Level 1, vreme je da predjemo na
Level2,  koji  donosi  par  novina. Dakle ponovo cemo kao i za prvi Level
pronaci  gde  se  to  porede uneti i tacan seriski broj. Ovo cemo uraditi
pomocu string referenci, kao i prosli put:

Text strings referenced in Crackme1:.text, item 8
 Address=00401355
 Disassembly=PUSH Crackme1.00403012
 Text string=ASCII "Level 2 Complated"

 Duplim klikom na ovaj string dolazimo ovde:

00401355  68 12304000   PUSH 00403012       ; |Text = "Level 2 Complated"

  Kao  i  prosli  put  skrolujemo  do  samog  pocetka CALLa i postavljamo
break-point na 00401309 posle cega u nasu metu unosimo lazni seriski broj
111111  i  pritiskamo dugme Register. Ovo nas zaustavlja izvrsavanje nase
mete  i  stavlja nas na nas break-point. Posto se sada nalazimo gde treba
mozemo  da  tracujemo  kroz  kod  sa F8. Ovo radimo sve dok ne dodjemo do
sledece adrese: 

0040131D  83F8 11      	CMP EAX,11
00401320  75 44        	JNZ SHORT 00401366

  Posto  se  ova provera CMP EAX,11 nalazi odmah ispod GetWindowTextA API
poziva  zakljucujemo  da je potrebna duzina seriskog broja 11h odnosno 17
karaktera.    Stoga    umesto    111111    kao    seriski   broj  unosimo
11111111111111111.  Ponovo  zastajemo  kod naseg break-pointa i tracujemo
kroz  kod  sve do JNZ skoka koji se ovaj put ne izvrsava! Tracujemo dalje
sve dok ne dodjemo do:

00401325  807E 08 2D    CMP BYTE PTR DS:[ESI+8],2D
00401329  75 3B         JNZ SHORT 00401366

  Sada  vidimo  da se jedan bajt poredi sa 2D, odnosno sa karakterom '-'.
Ako pogledamo malo ispod CPU windowa videcemo sledeci tekst: 

Stack DS:[0012FB08]=31 ('1')

 Njegovom selekcijom i klikom na Follow address in Dump videcemo ovo:

0012FB08  31 31 31 31 31 31 31 31  11111111
0012FB10  31 00 00 00 4C 10 40 00  1...L.@.

  Odnosno  videcemo  da  9  slovo  u unetom seriskom broju mora biti '-'.
Ponovo  unosimo  novi  seriski  broj  u  nasu  metu  samo sto sada umesto
predhodno  unesenog  seriskog  broja unosimo 11111111-11111111. Kada sada
budemo  stigli  do  poredjenja sa 2D videcemo da se ovaj JNZ skok vise ne
izvrsava i da cemo nastaviti sa daljim izvrsavanjem koda, stizuci do:

00401340  33C3         	XOR EAX,EBX
00401342  05 444F4F47  	ADD EAX,474F4F44
00401347  3D 504F5453   CMP EAX,53544F50

  Primetite  samo  da se pre ovoga nas seriski broj podelio na dve celine
koje  se  sada  nalaze  u  registrima  EAX  i  EBX. Posto su EAX i EBX ne
promenjeni u odnosu na unetu formu zakljucujemo da program trazi unosenje
seriskog  broja  u hexadecimalnoj formi. Da vidimo sta se dalje desava sa
registrima  EAX  i EBX. Oni se dalje medjusobno XORuju i na vrednost EAXa
se  dodaje  474F4F44,  posle cega se EAX poredi sa 53544F50. Dakle ponovo
imamo jednacinu:

(Deo_seriskog_1 XOR Deo_seriskog_2) + 474F4F44 = 53544F50

odnosno

53544F50 - 474F4F44 = Deo_seriskog_1 XOR Deo_seriskog_2
C05000C = Deo_seriskog_1 XOR Deo_seriskog_2

  Ali sta dalje? Sada imamo dva nepoznata dela seriskog broja! To stvarno
nema veze u ovom slucaju posto se ni jedan deo ne poredi direktno, vec se
samo  poredi  rezultat jednacine od gore. Posto se seriski broj proverava
na  ovaj  nacin  postoji  prakticno neogranicen broj seriskih brojeva. Ne
zavisno  od svega ovoga mi mozemo da predpostavimo da je Deo_seriskog_1 =
11111111 i onda imamo sledecu jednacinu:

C05000C = 11111111 XOR Deo_seriskog_2, odnosno
Deo_seriskog_2 = C05000C XOR 11111111.
Deo_seriskog_2 = 1D14111D.

    Tako    da  je  nas  seriski  broj  jednak  Deo_seriskog_1  +  '-'  +
Deo_seriskog_2.  I  konacno  jedan  o  mnogo  tacnih  seriskih brojeva je
11111111-1D14111D.  Ostavljam  vama da pronadjete jos par tacnih seriskih
brojeva za ovaj level.

--[ 0x05 ]---------------------------------------------[   Fishing  #3  ]

  Videli  smo da ni drugi level nije bio velika prepreka za nas, a sta se
to  nalazi  u  Levelu  3  ostaje  nam da vidimo. Bez neke velike mudrosti
pronalazimo  rutinu  koja  se  koristi za proveru levela 3, i postavljamo
break-point na adresu 0040137E posle cega mozemo da unesemo lazne podatke
u  nasu metu. Unecemo ap0x kao ime i 111111 kao seriski broj. Posle klika
na  dugme  Register  dolazimo  do  naseg  break-pointa.  Sada  mozemo  da
tracujemo dalje kroz kod sve dok ne dodjemo do ovde:

00401393  E8 28010000   CALL <JMP.&USER32.GetDlgItemInt>

 Kao sto znamo GetDlgItemTextA vraca sadrzaj nekog EditBoxa kao string, a
sta onda radi GetDlgItemInt? Mozete konsultovati dokumentaciju ili mozete
jednostavno  pogledati kod ispod i bice vam jasno da ova funkcija takodje
cita  EditBox  ali  umesto  stringa  vraca  vrednost  u brojevnom obliku.
Tracejuci dalje stizemo do koda:

004013A8  E8 19010000   CALL <JMP.&USER32.GetWindowTextA>

  koji  cita  ime koje smo uneli u metu. Posto je kod za proveru seriskog
broja  blizu  zakljucujemo  da  sledeci loop racuna tacan seriski broj na
osnovu unetog imena:

004013BB  /8D0C9B        /LEA ECX,DWORD PTR DS:[EBX+EBX*4]
004013BE  |8D0C4B        |LEA ECX,DWORD PTR DS:[EBX+ECX*2]
004013C1  |0FBE16        |MOVSX EDX,BYTE PTR DS:[ESI]
004013C4  |83C1 21       |ADD ECX,21
004013C7  |0FAFD1        |IMUL EDX,ECX
004013CA  |03FA          |ADD EDI,EDX
004013CC  |43            |INC EBX
004013CD  |46            |INC ESI
004013CE  |3BD8          |CMP EBX,EAX
004013D0  \7C E9         \JL SHORT Crackme1.004013BB

  Sam  algoritam  za generisanje seriskog broja i nije toliko bitan posto
cemo  mi samo pronaci tacan seriski broj za nase (moje) ime. Dakle mozemo
slobodno  da  postavimo  break-point  odmah ispod ovog loopa. Postavicemo
break-point na sledecu komandu:

004013D2  3B7D FC       CMP EDI,DWORD PTR SS:[EBP-4]

  Ovo radimo iz razloga sto se odmah ispod ove komande nalazi JNZ skok od
kojeg  zavisi  da  li  ce  se prikazati poruka o tacnom, odnosno netacnom
seriskom  broju.  Iz  ovog  razloga  cemo  pogledati  sta  se to nalazi u
registru EDI, ali i na adresi EBP-4. Ono sto vidimo u registrima je:

EAX 00000004
ECX 00000042
EDX 00000C60
EBX 00000004
ESP 0012FAEC
EBP 0012FB1C
ESI 0012FAFB
EDI 0000351C <- Vrednost koja se poredi
Dok na stacku (EBP-4) imamo sledece podatke:
Stack SS:[0012FB18]=0001B207 <- Vrednost sa kojom se EDI poredi
EDI=0000351C

  Posto znamo da je decimalno 111111 jednako 1B207h zakljucujemo da se na
adresi  EBP-4  nalazi  nas  uneti  seriski broj, sto ujedno znaci da se u
registru EDI nalazi tacan seriski broj! Ali da je to bas tako? Nije, 351C
nije    tacan  seriski  broj  za  ime  ap0x  iz  razloga  sto  se  porede
hexadecimalne  vrednosti unetog i izracunatog seriskog broja! Dakle posto
je  111111 pretvoreno u hexadecimalno i 351C mora biti pretvoreno nazad u
decimalno  kako bi uneti seriski broj bio ispravan! Ovo znaci da je tacan
seriski  broj  za ime ap0x ustvari 13596, sto mozemo i proveriti njegovim
unosenjem  u metu. I to bi bilo to sto se tice ove mete, ostao nam je jos
samo  Level 4, ali iz razloga sto je njegovo resanje isto kao i resavanje
Levela 3, to ostavljam vama da sami resite.

--[ 0x06 ]---------------------------------------------[ Outro & Greetz ]

  Uz  pomoc malo mozga i naseg voljenog [h]Olly-ja je kao sto smo videli,
izuzetno lako :) 

Greetz:

 SeekNDestroy   |   TSRh   |   EMiNENCE   |   CoolPHat   |   ELUSIVE 
b4d_s3c70r | B0r0 | loco | Kostolomac | Virus Krew | Jezgra | BlackHat

--[ EOF ]----------------------------------------------[  made by Ap0x  ]